#include "spi_soft.h"

/**
 * @desc  : 初始化
 * @date  : 2024-12-04
 * @author: AnRui
 */
void SPI_SOFT_INIT() {
    /******************* GPIO **********************/
    // SCL 
    rcu_periph_clock_enable(SPI_SOFT_CLK_RCU);
    gpio_mode_set(SPI_SOFT_CLK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SPI_SOFT_CLK_PIN);
    gpio_output_options_set(SPI_SOFT_CLK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, SPI_SOFT_CLK_PIN);

    // MOSI
    rcu_periph_clock_enable(SPI_SOFT_MOSI_RCU);
    gpio_mode_set(SPI_SOFT_MOSI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SPI_SOFT_MOSI_PIN);
    gpio_output_options_set(SPI_SOFT_MOSI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, SPI_SOFT_MOSI_PIN);

    // MISO	
    rcu_periph_clock_enable(SPI_SOFT_MISO_RCU);
    gpio_mode_set(SPI_SOFT_MISO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SPI_SOFT_MISO_PIN);
    /******************* io state ****************/
#if SPI0_CPOL
    SPI_SOFT_CLK(1);
#else
    SPI_SOFT_CLK(0);
#endif 
}


static void clk_start() {
#if SPI0_CPOL
    SPI_SOFT_CLK(1);
#else 
    SPI_SOFT_CLK(0);
#endif

}

static void clk_end() {
#if SPI0_CPOL
    SPI_SOFT_CLK(0);
#else 
    SPI_SOFT_CLK(1);
#endif
}

/**
 * @desc  : 写数据
 * @date  : 2024-12-04
 * @author: AnRui
 * @param :  data - {参数说明}:
 */
void SPI_SOFT_WRITE_BYTE(uint8_t data) {
    uint8_t i;
    for (i = 0; i < 8; i++) {
        clk_start();
        if (data & 0x80)
            SPI_SOFT_MOSI(1);
        else
            SPI_SOFT_MOSI(0);
        clk_end();
        data <<= 1;
    }
    clk_start();
}

/**
 * @desc  : 读数据
 * @date  : 2024-12-04
 * @author: AnRui
 * @return: uint8_t
 */
uint8_t SPI_SOFT_READ_BYTE() {
    uint8_t i, read = 0;
    for (i = 0; i < 8; i++) {
        clk_start();
        read <<= 1;
        if (SPI_SOFT_MISO_STATE()) {
            read++;
        }
        clk_end();
    }
    clk_start();
    return read;
}


/**
 *  @desc  :软实现方式 发送读取spi数据
 * @date  : 2025-02-28
 * @author: AnRui
 * @param :  data - {参数说明}:
 * @return: uint8_t
 * @note  : 正常是 scl上升沿的时候 读取数据 因为是手动 所有没办法
 *          所以在统一在scl高电平的时候读和写 不影响
 */
uint8_t SPI_SOFT_READ_WRITE_BYTE(uint8_t data) {

    uint8_t i;
    uint8_t read = 0;
    for (i = 0; i < 8; i++) {
        clk_start();
        // 写数据
        if (data & 0x80)
            SPI_SOFT_MOSI(1);
        else
            SPI_SOFT_MOSI(0);
        // clk_end();
        data <<= 1;
        // 读数据
        read <<= 1;
        if (SPI_SOFT_MISO_STATE()) {
            read++;
        }
        clk_end();
    }
    clk_start();
    return read;
}